﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Net;
using System.IO;
using System.Runtime.InteropServices;
using System.Management;
using System.Threading;

namespace Synthetic.MicroApps.SystemInfo
{
    public partial class Information : Form
    {
        public Information()
        {
            InitializeComponent();
        }

        private void Information_Load(object sender, EventArgs e)
        {
            this.Text = "System Information - " + Process.GetCurrentProcess().ProcessName.ToString() + " - pID " + Process.GetCurrentProcess().Id.ToString();
            InformationBox.Text = "Username: " + Environment.UserName;
            Thread SysInformation = new Thread(new ThreadStart(InfoThread));
            SysInformation.Start();
        }

        private void InfoThread()
        {
            AddLine("External IP Address: " + GetPublicIP());
            AddLine("Machine Name: " + Environment.MachineName);
            AddLine("Operating System: " + GetOSVersion());
            OperatingSystem osObj = System.Environment.OSVersion;
            AddLine("Service Pack: " + osObj.ServicePack);
            AddLine("");
            AddLine("Attached Drives:");
            string[] HDDs = Environment.GetLogicalDrives();
            foreach (string s in HDDs)
            {
                AddLine("\t " + s + " is a " + GetDiskType(s.Remove(1)));
            }

            AddLine("Desktop Directory: " + Environment.GetFolderPath(Environment.SpecialFolder.Desktop));
            AddLine("System Directory: " + Environment.SystemDirectory);
            AddLine("Program Files Directory: " + Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles));
            AddLine("");
            if (Is64BitOperatingSystem == false)
            {
                AddLine("System Architecture: x86 (32 Bit)");
            }
            else
            {
                AddLine("System Architecture: x64 (64 Bit)");
            }
            AddLine("Processor ID: " + GetProcessorID());
            AddLine("# of Processors: " + Environment.ProcessorCount);
            GetMemory();
            foreach (string s in GetInfo("Win32_BIOS"))
            {
                string data = s;
                data = data.Substring(data.IndexOf("\"") + 1);
                data = data.Remove(data.LastIndexOf("\""));
                AddLine("BIOS: " + data);
            }
            RemoveData("\"");
        }

        #region Detect if system is 64 bit
        private bool Is64BitProcess
        {
            get { return IntPtr.Size == 8; }
        }

        private bool Is64BitOperatingSystem
        {
            get
            {
                if (Is64BitProcess)
                    return true;
                bool isWow64;
                return ModuleContainsFunction("kernel32.dll", "IsWow64Process") && IsWow64Process(GetCurrentProcess(), out isWow64) && isWow64;
            }
        }

        private bool ModuleContainsFunction(string moduleName, string methodName)
        {
            IntPtr hModule = GetModuleHandle(moduleName);
            if (hModule != IntPtr.Zero)
                return GetProcAddress(hModule, methodName) != IntPtr.Zero;
            return false;
        }
        #endregion

        #region Import DLLs for use in other functions
        [DllImport("kernel32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        extern static bool IsWow64Process(IntPtr hProcess, [MarshalAs(UnmanagedType.Bool)] out bool isWow64);
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        extern static IntPtr GetCurrentProcess();
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        extern static IntPtr GetModuleHandle(string moduleName);
        [DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
        extern static IntPtr GetProcAddress(IntPtr hModule, string methodName);
        #endregion

        #region Add Text to InformationBox
        private delegate void AddLineDelegate(string data);
        private void AddLine(string data)
        {
            if (this.InformationBox.InvokeRequired)
            {
                // This is a worker thread so delegate the task.
                this.InformationBox.Invoke(new AddLineDelegate(this.AddLine), data);
            }
            else
            {
                // This is the UI thread so perform the task.
                this.InformationBox.Text += Environment.NewLine + data; ;
            }
        }

        private delegate void RemoveDataDelegate(string data);
        private void RemoveData(string data)
        {
            if (this.InformationBox.InvokeRequired)
            {
                // This is a worker thread so delegate the task.
                this.InformationBox.Invoke(new RemoveDataDelegate(this.RemoveData), data);
            }
            else
            {
                // This is the UI thread so perform the task.
                this.InformationBox.Text = this.InformationBox.Text.Remove(this.InformationBox.Text.IndexOf(data));
            }
        }
        #endregion

        private string GetPublicIP()
        {
            try
            {
                String direction = "";
                WebRequest request = WebRequest.Create("http://checkip.dyndns.org/");
                using (WebResponse response = request.GetResponse())
                using (StreamReader stream = new StreamReader(response.GetResponseStream()))
                {
                    direction = stream.ReadToEnd();
                }

                int first = direction.IndexOf("Address: ") + 9;
                int last = direction.LastIndexOf("</body>");
                direction = direction.Substring(first, last - first);
                return direction;
            }
            catch
            {
                return "Error Retrieving IP!";
            }
        }

        private string GetOSVersion()
        {
            string strVersion = "Unknown";
            switch (Environment.OSVersion.Platform)
            {
                case PlatformID.Win32S:
                    strVersion = "Windows 3.1";
                    break;
                case PlatformID.Win32Windows:
                    switch (Environment.OSVersion.Version.Minor)
                    {
                        case 0:
                            strVersion = "Windows 95";
                            break;
                        case 10:
                            if (Environment.OSVersion.Version.Revision.ToString() == "2222A")
                            {
                                strVersion = "Windows 98 Second Edition";
                            }
                            else
                            {
                                strVersion = "Windows 98";
                            }
                            break;
                        case 90:
                            strVersion = "Windows ME";
                            break;
                    }
                    break;
                case PlatformID.Win32NT:
                    switch (Environment.OSVersion.Version.Major)
                    {
                        case 3:
                            strVersion = "Windows NT 3.51";
                            break;
                        case 4:
                            strVersion = "Windows NT 4.0";
                            break;
                        case 5:
                            switch (Environment.OSVersion.Version.Minor)
                            {
                                case 0:
                                    strVersion = "Windows 2000";
                                    break;
                                case 1:
                                    strVersion = "Windows XP";
                                    break;
                                case 2:
                                    strVersion = "Windows 2003";
                                    break;
                            }
                            break;
                        case 6:
                            switch (Environment.OSVersion.Version.Minor)
                            {
                                case 0:
                                    strVersion = "Windows Vista";
                                    break;
                                case 1:
                                    strVersion = "Windows 7";
                                    break;
                            }
                            break;
                    }
                    break;
                case PlatformID.WinCE:
                    strVersion = "Windows CE";
                    break;
                case PlatformID.Unix:
                    strVersion = "Unix";
                    break;
            }
            return strVersion;
        }

        private string GetProcessorID()
        {
            string sCpuInfo = String.Empty;
            bool bSuccess = false;

            //*** Declare Management Class
            ManagementClass clsMgtClass = new ManagementClass("Win32_Processor");
            ManagementObjectCollection colMgtObjCol = clsMgtClass.GetInstances();

            //*** Loop Over Objects
            foreach (ManagementObject objMgtObj in colMgtObjCol)
            {
                //*** Only return cpuInfo from first CPU
                if (sCpuInfo == String.Empty)
                {
                    sCpuInfo = objMgtObj.Properties["ProcessorId"].Value.ToString();
                    bSuccess = true;
                }
            }

            return sCpuInfo;
        }

        private string GetDiskType(string drive)
        {
            ManagementObject diskDrive = new ManagementObject("win32_logicaldisk.deviceid=\"" + drive + ":\"");
            string DriveType = diskDrive["DriveType"].ToString();
            switch (DriveType)
            {
                case "0":
                    DriveType = "Unknown";
                    break;
                case "1":
                    DriveType = "No Root Directory";
                    break;
                case "2":
                    DriveType = "Removable Disk";
                    break;
                case "3":
                    DriveType = "Local Disk";
                    break;
                case "4":
                    DriveType = "Network Drive";
                    break;
                case "5":
                    DriveType = "Compact Disc";
                    break;
                case "6":
                    DriveType = "RAM Disk";
                    break;
                default:
                    DriveType = "Unknown";
                    break;
            }
            return DriveType;
        }

        private void GetMemory()
        {
            double totalCapacity = 0;
            ObjectQuery objectQuery = new ObjectQuery("select * from Win32_PhysicalMemory");
            ManagementObjectSearcher searcher = new
            ManagementObjectSearcher(objectQuery);
            ManagementObjectCollection vals = searcher.Get();

            foreach (ManagementObject val in vals)
            {
                totalCapacity += System.Convert.ToDouble(val.GetPropertyValue("Capacity"));
            }

            AddLine("Total RAM: " + (totalCapacity / 1073741824) + "GB");
        }

        private List<string> GetInfo(string Key)
        {
            List<string> infos = new List<string>();
            ManagementObjectSearcher searcher = new ManagementObjectSearcher("select * from " + Key);
            foreach (ManagementObject share in searcher.Get())
            {
                infos.Add(share.ToString());
            }
            return infos;
        }
    }
}
